package com.ydzh.kfqgwvisitor.util;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import javax.xml.bind.DatatypeConverter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.util.Base64;

/**
 * @description: 图片工具类
 * @param:
 * @return:
 * @author: zcj
 * @date: 2021/11/2
 */
@Slf4j
public class PicUtils {

    public static void main(String[] args) throws IOException {
        String s = resizeImageTo7M(getImgStr("C:\\Users\\Cheng\\Desktop\\1.jpg"));
        System.out.println(s);
       /* String a = "data:123";
        System.out.println(a.substring(5, a.length()));*/
        // String s1 = commpressPicForScale("C:\\Users\\Administrator\\Pictures\\Camera Roll\\1.png", "C:\\Users\\Administrator\\Pictures\\Camera Roll\\123.jpg", 2048, 0.8, 1, 1);

    }

    public static BufferedImage base64ToBufferedImage(String base64) {
        Base64.Decoder decoder = Base64.getDecoder();
        try {
            byte[] bytes1 = decoder.decode(base64);
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
            return ImageIO.read(bais);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 将图片转换成Base64编码
     *
     * @param imgFile 待处理图片
     * @return
     */
    public static String getImgStr(String imgFile) {
        // 将图片文件转化为字节数组字符串，并对其进行Base64编码处理

        InputStream in = null;
        byte[] data = null;
        // 读取图片字节数组
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(data);
    }

    /**
     * 对字节数组字符串进行Base64解码并生成图片
     *
     * @param imgStr      图片数据
     * @param imgFilePath 保存图片全路径地址
     * @return
     */
    public static boolean generateImage(String imgStr, String imgFilePath) throws IOException {
        //
        if (imgStr == null) // 图像数据为空
            return false;

        byte[] b = Base64.getDecoder().decode(imgStr);
        for (int i = 0; i < b.length; ++i) {
            if (b[i] < 0) {// 调整异常数据
                b[i] += 256;
            }
        }
        // 生成jpg图片
        OutputStream out = new FileOutputStream(imgFilePath);
        out.write(b);
        out.flush();
        out.close();
        return true;
    }

    /**
     * @description: base64转换成BufferedImage:
     * @param: [base64string]
     * @return: java.awt.image.BufferedImage
     * @author: zcj
     * @date: 2021/11/2
     */
    public static BufferedImage base64String2BufferedImage(String base64string) throws IOException {
        InputStream stream = BaseToInputStream(base64string);
        return ImageIO.read(stream);
    }

    /**
     * @description: Base64转换成InputStream
     * @param: [base64string]
     * @return: java.io.InputStream
     * @author: zcj
     * @date: 2021/11/2
     */
    private static InputStream BaseToInputStream(String base64string) {
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] decode = decoder.decode(base64string);
        return new ByteArrayInputStream(decode);
    }

    /**
     * @description: BufferedImage转换成base64，在这里需要设置图片格式，如下是jpg格式图片
     * @param: [bufferedImage]
     * @return: java.lang.String
     * @author: zcj
     * @date: 2021/11/2
     */
    public static String imageToBase64(BufferedImage bufferedImage) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", baos);
        return new String(Base64.getEncoder().encode((baos.toByteArray())));
    }

    public static String resizeImageTo2M(String base64Img) throws IOException {
        /*Base64.Decoder decoder = Base64.getDecoder();
        byte[] img = decoder.decode(base64Img);
        log.info("图片的base64大小为：{}", img.length);
        byte[] bytes = commpressPicCycle(img, 2048, 0.8);
        return Base64.getEncoder().encodeToString(bytes);*/

        //获取图片信息
        BufferedImage bim = base64String2BufferedImage(base64Img);
        int srcWidth = bim.getWidth();
        int srcHeight = bim.getHeight();

        //先转换成jpg
        Thumbnails.Builder builder = Thumbnails.of(bim).outputFormat("jpg");

        //宽高均小，指定原大小
        builder.size(srcWidth, srcHeight);

        // 写入到内存
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
        builder.toOutputStream(baos);

        // 递归压缩，直到目标文件大小小于desFileSize
        byte[] bytes = commpressPicCycle(baos.toByteArray(), 200, 0.8);
        log.info("压缩后图片的长度{}", bytes.length);
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static String resizeImageTo7M(String base64Img) throws IOException {
        byte[] img = DatatypeConverter.parseBase64Binary(base64Img);
        log.info("图片的base64大小为：{}", img.length);
        byte[] bytes = commpressPicCycle(img, 200, 0.8);
        /*ByteArrayInputStream in = new ByteArrayInputStream(bytes);    //将b作为输入流；

        BufferedImage image = ImageIO.read(in);
        return imageToBase64(image);*/
        return DatatypeConverter.printBase64Binary(bytes);
    }

    /**
     * 根据指定大小和指定精度压缩图片
     *
     * @param srcPath      源图片地址
     * @param desPath      目标图片地址
     * @param desFileSize  指定图片大小，单位kb
     * @param accuracy     精度，递归压缩的比率，建议小于0.9
     * @param desMaxWidth  目标最大宽度
     * @param desMaxHeight 目标最大高度
     * @return 目标文件路径
     */
    public static String commpressPicForScale(String srcPath, String desPath,
                                              long desFileSize, double accuracy, int desMaxWidth, int desMaxHeight) {
        if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(srcPath)) {
            return null;
        }
        if (!new File(srcPath).exists()) {
            return null;
        }
        try {
            File srcFile = new File(srcPath);
            long srcFileSize = srcFile.length();
            System.out.println("源图片：" + srcPath + "，大小：" + srcFileSize / 1024
                    + "kb");
            //获取图片信息
            BufferedImage bim = ImageIO.read(srcFile);
            int srcWidth = bim.getWidth();
            int srcHeight = bim.getHeight();

            //先转换成jpg
            Thumbnails.Builder builder = Thumbnails.of(srcFile).outputFormat("jpg");

            /*// 指定大小（宽或高超出会才会被缩放）
            if (srcWidth > desMaxWidth || srcHeight > desMaxHeight) {
                builder.size(desMaxWidth, desMaxHeight);
            } else {*/
            //宽高均小，指定原大小
            builder.size(srcWidth, srcHeight);
            // }

            // 写入到内存
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
            builder.toOutputStream(baos);

            // 递归压缩，直到目标文件大小小于desFileSize
            byte[] bytes = commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);

            // 输出到文件
            File desFile = new File(desPath);
            FileOutputStream fos = new FileOutputStream(desFile);
            fos.write(bytes);
            fos.close();

            System.out.println("目标图片：" + desPath + "，大小" + desFile.length() / 1024 + "kb");
            System.out.println("图片压缩完成！");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return desPath;
    }

    public static byte[] commpressPicCycle(byte[] bytes, long desFileSize, double accuracy) throws IOException {
        // File srcFileJPG = new File(desPath);
        long srcFileSizeJPG = bytes.length;
        // 这里对字符串进行判断因为转字符串是原来的133%左右
        // int length = Base64.getEncoder().encodeToString(bytes).length();
        log.info("压缩前的长度为：{}，转换为KB：{},转换M为：{}", srcFileSizeJPG, srcFileSizeJPG / 1024, srcFileSizeJPG / 1024 / 1024);
        // 2、判断大小，如果小于500kb，不压缩；如果大于等于500kb，压缩
        if (srcFileSizeJPG <= desFileSize * 1024) {
            log.info("完成压缩");
            return bytes;
        }
        // 计算宽高
        BufferedImage bim = ImageIO.read(new ByteArrayInputStream(bytes));
        int srcWdith = bim.getWidth();
        int srcHeigth = bim.getHeight();
        int desWidth = new BigDecimal(srcWdith).multiply(
                new BigDecimal(accuracy)).intValue();
        int desHeight = new BigDecimal(srcHeigth).multiply(
                new BigDecimal(accuracy)).intValue();
        log.info("要压缩的宽度为：{},长度为：{}", desWidth, desHeight);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
        Thumbnails.of(new ByteArrayInputStream(bytes)).size(desWidth, desHeight).outputQuality(accuracy).toOutputStream(baos);
        return commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);
    }

    public static String saveMinPhoto(String srcURL, double comBase,
                                      double scale) throws Exception {
        byte[] bytes1 = cn.hutool.core.codec.Base64.decode(srcURL);
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
        Image src = ImageIO.read(bais);
        int srcHeight = src.getHeight(null);
        int srcWidth = src.getWidth(null);
        int deskHeight = 0;// 缩略图高
        int deskWidth = 0;// 缩略图宽
        double srcScale = (double) srcHeight / srcWidth;
        /**缩略图宽高算法*/
        if ((double) srcHeight > comBase || (double) srcWidth > comBase) {
            if (srcScale >= scale || 1 / srcScale > scale) {
                if (srcScale >= scale) {
                    deskHeight = (int) comBase;
                    deskWidth = srcWidth * deskHeight / srcHeight;
                } else {
                    deskWidth = (int) comBase;
                    deskHeight = srcHeight * deskWidth / srcWidth;
                }
            } else {
                if ((double) srcHeight > comBase) {
                    deskHeight = (int) comBase;
                    deskWidth = srcWidth * deskHeight / srcHeight;
                } else {
                    deskWidth = (int) comBase;
                    deskHeight = srcHeight * deskWidth / srcWidth;
                }
            }
        } else {
            deskHeight = srcHeight;
            deskWidth = srcWidth;
        }
        BufferedImage tag = new BufferedImage(deskWidth, deskHeight, BufferedImage.TYPE_3BYTE_BGR);
        tag.getGraphics().drawImage(src, 0, 0, deskWidth, deskHeight, null); //绘制缩小后的图
        //输出流
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        ImageIO.write(tag, "jpg", stream);
        String base64 = cn.hutool.core.codec.Base64.encode(stream.toByteArray());
        stream.flush();
        stream.close();
        return base64;
    }
   /* public static boolean generateImage(String imgStr, String imgFilePath) {
        if (imgStr == null) {
            return false;
        }
        Base64.Decoder decoder = Base64.getDecoder();
        try {

            // Base64解码
            byte[] bytes = decoder.decode(imgStr);
            for (int i = 0; i < bytes.length; ++i) {
                // 调整异常数据
                if (bytes[i] < 0) {
                    bytes[i] += 256;
                }
            }
            // 生成jpeg图片
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(bytes);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }*/

}